package com.kpmg.datalake.web.controller;

import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.kpmg.datalake.common.controller.BaseController;
import com.kpmg.datalake.common.dynamicdatasource.DBTypeEnum;
import com.kpmg.datalake.common.service.CommonExecuteService;
import com.kpmg.datalake.common.service.IProjectService;
import com.kpmg.datalake.common.utils.AssertUtil;
import com.kpmg.datalake.common.utils.DateUtils;
import com.kpmg.datalake.common.utils.signutils.Md5Util;
import com.kpmg.datalake.common.vo.KeyAndValueDTO;
import com.kpmg.datalake.common.vo.ServerResponse;
import com.kpmg.datalake.db.model.Project;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 通用sql执行服务
 *
 * @author Alex.zhao [alex.zhao@kpmg.com]
 * @since Created on azhao6 on 2018-09-06 14:25:00
 */
@RestController
@RequestMapping("/plsql")
public class CommSqlController extends BaseController {


  @Resource
  private IProjectService projectService;
  @Resource
  private CommonExecuteService commonExecuteService;

  @PostMapping("getProjectList")
  public ServerResponse<ArrayList<Project>> getProjectList() {
    Wrapper<Project> entryWrapper = new EntityWrapper<>();
    entryWrapper.orderBy("crt_dt", false);
    return super.doSuccess(new ArrayList<>(projectService.selectList(entryWrapper)));
  }

  @PostMapping("execData/{date}")
  public ServerResponse<JSONArray> execData(@RequestBody KeyAndValueDTO<String, String> data,
      @PathVariable String date) {
    JSONArray jsonArray = new JSONArray();
    try {
      AssertUtil.assertTrue(
          Md5Util.md5Encode(
              Md5Util.md5Encode(DateUtils.format(new Date(), DateUtils.YYYYMMDD), null),
              null).equals(date),
          "签名非法");
      AssertUtil.assertNotEmpty(data.getValue());
      List<SQLStatement> sqlList = SQLUtils
          .parseStatements(data.getValue(), DBTypeEnum.ORACLE.getDbType());
      for (SQLStatement sqlStatement : sqlList) {
        try {
          //获取sql 执行输出器
          StringBuilder out = new StringBuilder();
          OracleOutputVisitor oracleOutputVisitor = new OracleOutputVisitor(out);
          sqlStatement.accept(oracleOutputVisitor);
          //获取sql执行器
          String sqlText = SQLUtils.format(out.toString(), DBTypeEnum.ORACLE.getDbType());
          String databaseId = StringUtils.isEmpty(data.getKey()) ? "@@" : data.getKey();
          if (sqlStatement instanceof SQLExprStatement) {
            jsonArray.add("sql语法错误：" + sqlText);
          } else if (sqlStatement instanceof SQLSelectStatement) {
            Page<Map<String, Object>> page = new Page<>(1, 20);
            jsonArray.add(commonExecuteService.queryPageByString(databaseId, page, sqlText));
          } else {
            jsonArray.add("受影响行数" + commonExecuteService.updateByString(databaseId, sqlText));
          }
        } catch (BadSqlGrammarException | UncategorizedSQLException e) {
          jsonArray.add(e.getCause().getMessage());
        } catch (Exception e) {
          jsonArray.add(e.getMessage());
        }
      }
    } catch (Exception e) {
      jsonArray.add(e.getMessage());
      return super.doSuccess(jsonArray);
    }
    return super.doSuccess(jsonArray);
  }


}
